﻿using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using UFSoft.UBF.Business;
using UFSoft.UBF.Business.Tool;
using UFSoft.UBF.PL.Engine;
using UFSoft.UBF.PL.ObjectAccess;
using UFSoft.UBF.Util.Log;

namespace UFIDA.U9.CusDev.AITPlugInBE
{
    internal class LogUtils
    {
        //public static ILogger logger = LoggerManager.GetLogger(typeof(ProcessForAIT));
        public static ILogger logger = LoggerManager.GetLogger("AIT");

        public static void Log(string msg)
        {
            logger.Error(msg);
        }

        private static bool isFilter(String attr,object valobj)
        {
            //过滤部分属性
            if (attr == "CreatedOn" || attr == "CreatedBy" || attr == "ModifiedOn"
                || attr == "ModifiedBy" || attr == "ID")
                return true;
            else if (valobj is Decimal && (Decimal)valobj == 0)
                return true;
            else if (valobj is Boolean && (Boolean)valobj == false)
                return true;
            else
                return false;
        }

        /// <summary>
        /// 递归实体属性输出日志
        /// </summary>
        /// <param name="entity">实体</param>
        /// <param name="config">实体配置</param>
        private static void AttrLog(BusinessEntity entity)
        {
            if(entity == null) return;

            //输出本实体日志
            AttrLogDetail(entity);

            //List<string> elines = EntityUtils.getLines(entity);
            List<string> ass = EntityUtils.getAssociation(entity);
            if (ass == null || ass.Count == 0)
                return;

            foreach (string assName in ass)
            {
                object relobj = entity.GetRelation(assName);
                if (relobj == null) continue;

                if (relobj is IList)
                {
                    foreach (object line in (IList)relobj)
                    {
                        if (line is BusinessEntity)
                        {
                            //JToken config1 = config[line.GetType().FullName];
                            //递归输出子实体日志
                            AttrLog(line as BusinessEntity);
                        }
                    }
                }
                else if (relobj is BusinessEntity)
                {
                    AttrLog(relobj as BusinessEntity);
                }

            }
        }

        private static void AttrLogDetail(BusinessEntity entity)
        {
            //获取变化属性
            List<string> attrs = entity.GetChangedAttributes();
            if (attrs == null || attrs.Count <= 0) return;
            //输出实体变化属性名称
            //使用 ExtendHelpAPI 获取实体和字段的中文名
            string entName = ExtendHelpAPI.GetEntityResource(entity.GetType().FullName);
            logger.Error($"-----------------[{entName}]------------------------");
            logger.Error($"实体全名:[{entity.GetType().FullName}],属性:[{entity.ToBusinessName()}],操作:[{entity.SysState}]");
            //logger.Error($"变更属性:[{String.Join("],[", attrs)}]");

            foreach (string attr in attrs)
            {
                //输出变化属性的具体前后变化值
                object valobj = entity[attr];
                string valstr = "null";
                if (valobj != null)
                    valstr = valobj is BusinessEntity ? ((BusinessEntity)valobj).ToBusinessName() : valobj.ToString();
                object oldval = entity.OriginalData != null ? entity.OriginalData.GetValue(attr) : "";
                //获取属性中文名
                string attrName = ExtendHelpAPI.GetAttrResource(entity.GetType().FullName, attr);
                if (entity.SysState == ObjectState.Inserted)
                {
                    //过滤部分属性
                    if (isFilter(attr, valobj)) continue;
                }

                //日志输出
                logger.Error($"  属性:[{attr}],名称:[{attrName}],类型:[{valobj?.GetType()}],值:[{valstr}],旧值:[{oldval}]");
            }
        }

        public static void EntityLog(BusinessEntity entity)
        {
            //输出本实体日志
            if (entity.SysState == ObjectState.Updated)
            {
                string entityName = ExtendHelpAPI.GetEntityResource(entity.GetType().FullName);
                logger.Error("");
                logger.Error($"================EntityLog({entityName}) Begin====================");
                AttrLog(entity);
                logger.Error($"================EntityLog({entityName}) End======================");
            }
        }

        public static JObject CreateJson(BusinessEntity entity)
        {
            
            List<string> attrs = entity.GetChangedAttributes();
            if (attrs == null || attrs.Count <= 0) return null;
            //创建JSON对象
            JObject json = new JObject();
            foreach (string attr in attrs)
            {
                object valobj = entity[attr];
                if (entity.SysState == ObjectState.Inserted)
                {
                    //新增时,过滤部分属性
                    if (isFilter(attr, valobj)) continue;
                }
                //构造特殊val
                if (valobj is BusinessEntity)
                {
                    if ((valobj as BusinessEntity).Values.Contains("Code"))
                    {
                        //构造JSON子对象
                        valobj = new JObject(
                            new JProperty("Code", (valobj as BusinessEntity).Values["Code"])
                            );
                    }
                    else
                    {
                        //构造JSON子对象
                        valobj = new JObject(
                            new JProperty("ID", (valobj as BusinessEntity).Values["ID"])
                            );
                    }
                }
                //JSON对象中添加属性
                json.Add(new JProperty(attr, valobj));
            }
            //获取子实体属性名称集合
            List<string> asslist = EntityUtils.getAssociation(entity);
            if (asslist == null || asslist.Count == 0)
                return json;
            foreach (string assName in asslist)
            {
                //依据属性名称,获取子实体
                object relobj = entity.GetRelation(assName);
                if (relobj == null) continue;

                if (relobj is IList)
                {
                    //构造JSON集合
                    JArray jarr = new JArray();
                    foreach (object line in (IList)relobj)
                    {
                        if (line is BusinessEntity)
                        {
                            //输出子实体日志
                            JObject linejson = CreateJson(line as BusinessEntity);
                            if (linejson != null)
                            {
                                //JSON集合中添加JSON对象
                                jarr.Add(linejson);
                            }
                        }
                    }
                    //JSON对象添加属性
                    json.Add(new JProperty(assName, jarr));
                }else if(relobj is BusinessEntity)
                {
                    JObject reljson = CreateJson(relobj as BusinessEntity);
                    //JSON对象中添加属性
                    if (json[assName] != null)
                    {
                        //避免在上面代码中重复添加
                        //料品测试中[InspectionInfo]等属性会在上面代码中添加为ID对象
                        json.Remove(assName);
                    }
                    json.Add(new JProperty(assName, reljson));
                }
            }
            return json;
        }

        public static void JsonLog(BusinessEntity entity)
        {
            if (entity.SysState != ObjectState.Inserted)
                return;

            //插入时记录json文件
            JObject json = CreateJson(entity);
            String filepath = $"\\log\\{entity.GetType().Name}.json";
            logger.Error("");
            logger.Error($"===JsonLog=== JSON文件:{filepath}");
            FileUtils.Write(filepath, json.ToString());

        }
    }
}
